<template>
  <div id="root">
    <div class="bg-overlay"></div>
    <header>
      <Publicity v-show="!running" />
      <el-button class="res" type="text" @click="showResult = true">
        抽奖结果
      </el-button>
      <el-button class="con" type="text" @click="showConfig = true">
        抽奖配置
      </el-button>
      <el-button 
        class="admin" 
        type="text" 
        style="z-index: 9999"
        @click.stop="showAdminLogin = true"
      >
        {{ $store.state.isAdmin ? '退出管理' : '管理员登录' }}
      </el-button>
    </header>
    <div id="main" :class="{ mask: showRes }"></div>
    <div id="tags">
      <ul v-for="item in datas" :key="item.key">
        <li>
          <a
            href="javascript:void(0);"
            :style="{
              color: '#fff',
              textShadow: '1px 1px 3px rgba(0, 0, 0, 0.5)',
              fontWeight: 'bold'
            }"
          >
            {{ item.name || item.key }}
            <img v-if="item.photo" :src="item.photo" :width="50" :height="50" />
          </a>
        </li>
      </ul>
    </div>
    <transition name="bounce">
      <div id="resbox" v-show="showRes">
        <div class="result-header">
          <p>{{ categoryName }}抽奖结果：</p>
          <i class="el-icon-close close-btn" @click="showRes = false"></i>
        </div>
        <div class="container">
          <span
            v-for="item in resArr"
            :key="item"
            class="itemres"
            :style="resCardStyle"
            :data-id="item"
            @click="showRes = false"
            :class="{
              numberOver:
                !!photos.find((d) => d.id === item) ||
                !!list.find((d) => d.key === item),
            }"
          >
            <span class="cont" v-if="!photos.find((d) => d.id === item)">
              <span :style="{ fontSize: '32px', color: 'rgb(0, 165, 181)' }">
                {{ list.find(d => d.key === item)?.name || item }}
              </span>
            </span>
            <img
              v-if="photos.find((d) => d.id === item)"
              :src="photos.find((d) => d.id === item).value"
              alt="photo"
              :width="160"
              :height="160"
            />
          </span>
        </div>
      </div>
    </transition>

    <el-button
      class="audio"
      type="text"
      @click="
        () => {
          playAudio(!audioPlaying);
        }
      "
    >
      <i
        class="iconfont"
        :class="[audioPlaying ? 'iconstop' : 'iconplay1']"
      ></i>
    </el-button>

    <LotteryConfig 
      :visible.sync="showConfig" 
      @resetconfig="reloadTagCanvas"
      @openImportList="openImportList"
    />
    <Tool
      ref="tool"
      @toggle="toggle"
      @resetConfig="reloadTagCanvas"
      @getPhoto="getPhoto"
      :running="running"
      :closeRes="closeRes"
    />
    <Result :visible.sync="showResult"></Result>

    <audio
      id="audiobg"
      preload="auto"
      controls
      autoplay
      loop
      @play="playHandler"
      @pause="pauseHandler"
    >
      <source :src="audioSrc" />
      你的浏览器不支持audio标签
    </audio>

    <el-dialog
      title="管理员登录"
      :visible.sync="showAdminLogin"
      width="400px"
      :close-on-click-modal="false"
      :modal-append-to-body="true"
      :append-to-body="true"
      class="admin-login-dialog"
    >
      <template v-if="!$store.state.isAdmin">
        <el-input
          v-model="adminPassword"
          type="password"
          placeholder="请输入管理密码"
          @keyup.enter.native="handleAdminLogin"
        ></el-input>
        <div style="margin-top: 20px; text-align: right;">
          <el-button @click="showAdminLogin = false">取消</el-button>
          <el-button type="primary" @click="handleAdminLogin">确定</el-button>
        </div>
      </template>
      <template v-else>
        <p style="text-align: center; margin: 0;">确定要退出管理员模式吗？</p>
        <div style="margin-top: 20px; text-align: right;">
          <el-button @click="showAdminLogin = false">取消</el-button>
          <el-button type="primary" @click="handleAdminLogout">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script>
import LotteryConfig from '@/components/LotteryConfig';
import Publicity from '@/components/Publicity';
import Tool from '@/components/Tool';
import bgaudio from '@/assets/bg.mp3';
import beginaudio from '@/assets/begin.mp3';
import {
  getData,
  configField,
  resultField,
  newLotteryField,
  conversionCategoryName,
  listField,
} from '@/helper/index';
import { luckydrawHandler } from '@/helper/algorithm';
import Result from '@/components/Result';
import { database, DB_STORE_NAME } from '@/helper/db';
import { login, logout } from '@/helper/auth';

export default {
  name: 'App',

  components: { LotteryConfig, Publicity, Tool, Result },

  computed: {
    resCardStyle() {
      const style = { fontSize: '30px' };
      const { number } = this.config;
      if (number < 100) {
        style.fontSize = '100px';
      } else if (number < 1000) {
        style.fontSize = '80px';
      } else if (number < 10000) {
        style.fontSize = '60px';
      }
      return style;
    },
    config: {
      get() {
        return this.$store.state.config;
      }
    },
    result: {
      get() {
        return this.$store.state.result;
      },
      set(val) {
        this.$store.commit('setResult', val);
      }
    },
    list() {
      return this.$store.state.list;
    },
    allresult() {
      let allresult = [];
      for (const key in this.result) {
        if (this.result.hasOwnProperty(key)) {
          const element = this.result[key];
          allresult = allresult.concat(element);
        }
      }
      return allresult;
    },
    datas() {
      const arr = [];
      if (this.list.length === 0) {
        for (let i = 1; i <= this.config.number; i++) {
          arr.push({
            key: i,
            name: String(i)
          });
        }
        return arr;
      }

      this.list.forEach((item) => {
        if (this.photos.find((d) => d.id === item.key)) {
          arr.push({
            key: item.key,
            name: '',
            photo: this.photos.find((d) => d.id === item.key).value,
          });
        } else {
          arr.push({
            ...item,
            name: item.name || item.key
          });
        }
      });
      return arr;
    },
    categoryName() {
      return conversionCategoryName(this.category);
    },
    photos() {
      return this.$store.state.photos;
    },
    isAdmin() {
      return this.$store.state.isAdmin;
    }
  },
  created() {
    const data = getData(configField);
    if (data) {
      this.$store.commit('setConfig', Object.assign({}, data));
    }
    const result = getData(resultField);
    if (result) {
      this.$store.commit('setResult', result);
    }

    const newLottery = getData(newLotteryField);
    if (newLottery) {
      const config = this.config;
      newLottery.forEach((item) => {
        this.$store.commit('setNewLottery', item);
        if (!config[item.key]) {
          this.$set(config, item.key, 0);
        }
      });
      this.$store.commit('setConfig', config);
    }

    const list = getData(listField);
    if (list) {
      this.$store.commit('setList', list);
    }
  },

  data() {
    return {
      running: false,
      showRes: false,
      showConfig: false,
      showResult: false,
      resArr: [],
      category: '',
      audioPlaying: false,
      audioSrc: bgaudio,
      showAdminLogin: false,
      adminPassword: ''
    };
  },
  watch: {
    photos: {
      deep: true,
      handler() {
        this.$nextTick(() => {
          this.reloadTagCanvas();
        });
      },
    },
  },
  mounted() {
    this.startTagCanvas();
    setTimeout(() => {
      this.getPhoto();
    }, 1000);
    window.addEventListener('resize', this.reportWindowSize);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.reportWindowSize);
  },
  methods: {
    reportWindowSize() {
      const AppCanvas = this.$el.querySelector('#rootcanvas');
      if (AppCanvas.parentElement) {
        AppCanvas.parentElement.removeChild(AppCanvas);
      }
      this.startTagCanvas();
    },
    playHandler() {
      this.audioPlaying = true;
    },
    pauseHandler() {
      this.audioPlaying = false;
    },
    playAudio(type) {
      if (type) {
        this.$el.querySelector('#audiobg').play();
      } else {
        this.$el.querySelector('#audiobg').pause();
      }
    },
    loadAudio() {
      this.$el.querySelector('#audiobg').load();
      this.$nextTick(() => {
        this.$el.querySelector('#audiobg').play();
      });
    },
    getPhoto() {
      database.getAll(DB_STORE_NAME).then(res => {
        if (res && res.length > 0) {
          this.$store.commit('setPhotos', res);
        }
      });
    },
    speed() {
      return [0.1 * Math.random() + 0.01, -(0.1 * Math.random() + 0.01)];
    },
    createCanvas() {
      const canvas = document.createElement('canvas');
      canvas.width = document.body.offsetWidth;
      canvas.height = document.body.offsetHeight;
      canvas.id = 'rootcanvas';
      this.$el.querySelector('#main').appendChild(canvas);
    },
    startTagCanvas() {
      this.createCanvas();
      const { speed } = this;
      window.TagCanvas.Start('rootcanvas', 'tags', {
        textColour: null,
        initial: speed(),
        dragControl: 1,
        textHeight: 20,
        noSelect: true,
        lock: 'xy',
      });
    },
    reloadTagCanvas() {
      window.TagCanvas.Reload('rootcanvas');
    },
    closeRes() {
      this.showRes = false;
    },
    toggle(form) {
      const { speed, config } = this;
      if (this.running) {
        this.audioSrc = bgaudio;
        this.loadAudio();

        window.TagCanvas.SetSpeed('rootcanvas', speed());
        this.showRes = true;
        this.running = !this.running;
        this.$nextTick(() => {
          this.reloadTagCanvas();
        });
      } else {
        this.showRes = false;
        if (!form) {
          return;
        }

        this.audioSrc = beginaudio;
        this.loadAudio();

        const { number } = config;
        const { category, mode, qty, remain, allin } = form;
        let num = 1;
        if (mode === 1 || mode === 5) {
          num = mode;
        } else if (mode === 0) {
          num = remain;
        } else if (mode === 99) {
          num = qty;
        }
        const resArr = luckydrawHandler(
          number,
          allin ? [] : this.allresult,
          num,
          this.$store.state.presetWinners,
          category,
          this.$store.state.excludedList
        );
        this.resArr = resArr;

        this.category = category;
        if (!this.result[category]) {
          this.$set(this.result, category, []);
        }
        const oldRes = this.result[category] || [];
        const data = Object.assign({}, this.result, {
          [category]: oldRes.concat(resArr),
        });
        this.result = data;
        window.TagCanvas.SetSpeed('rootcanvas', [5, 1]);
        this.running = !this.running;
      }
    },
    handleAdminLogin() {
      if (!this.adminPassword) {
        this.$message.warning('请输入管理密码');
        return;
      }
      if (login(this.adminPassword)) {
        this.$message.success('登录成功');
        this.$store.commit('setIsAdmin', true);
        this.showAdminLogin = false;
        this.adminPassword = '';
      } else {
        this.$message.error('密码错误');
      }
    },
    handleAdminLogout() {
      logout();
      this.$store.commit('setIsAdmin', false);
      this.showAdminLogin = false;
      this.$message.success('已退出管理员模式');
    },
    openImportList() {
      this.showConfig = false;
      this.$nextTick(() => {
        this.$refs.tool.handleOpenImportList();
      });
    }
  },
};
</script>
<style lang="scss">
#root {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background-color: #fff;
  
  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-image: url('./assets/bg1.jpg');
    width: 100%;
    height: 100%;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    z-index: 0;
  }
  
  .bg-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.6);
    pointer-events: none;
    z-index: 0;
  }
  
  > *:not(.bg-overlay):not(.audio):not(#tool):not(#resbox) {
    position: relative;
    z-index: 2;
  }
  .mask {
    -webkit-filter: blur(5px);
    filter: blur(5px);
  }
  header {
    height: 50px;
    line-height: 50px;
    position: relative;
    .el-button {
      position: absolute;
      top: 17px;
      padding: 0;
      z-index: 3;
      &.con {
        right: 20px;
      }
      &.res {
        right: 100px;
      }
      &.admin {
        right: 180px;
      }
    }
  }
  .audio {
    position: absolute;
    top: 100px;
    right: 30px;
    width: 40px;
    height: 40px;
    line-height: 40px;
    border: 1px solid #fff;
    border-radius: 50%;
    padding: 0;
    text-align: center;
    z-index: 3;
    .iconfont {
      position: relative;
      left: 1px;
    }
  }
  #tool {
    z-index: 3;
  }
  .bounce-enter-active {
    animation: bounce-in 1.5s;
  }
  .bounce-leave-active {
    animation: bounce-in 0s reverse;
  }
  .el-dialog__wrapper {
    z-index: 9999 !important;
  }
  .v-modal {
    z-index: 9998 !important;
  }
  .admin {
    position: relative;
    z-index: 9999 !important;
  }
  .admin-login-dialog {
    position: relative;
    z-index: 10000 !important;
    
    .el-dialog {
      margin-top: 15vh !important;
    }
    .el-dialog__body {
      padding: 20px;
    }
  }
}
#main {
  height: 100%;
}

#resbox {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 90%;
  max-width: 1400px;
  max-height: 80vh;
  overflow: hidden;
  transform: translateX(-50%) translateY(-50%);
  text-align: center;
  z-index: 10;
  
  .result-header {
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    margin-bottom: 20px;
    
    p {
      margin: 0;
      font-size: 36px;
      color: rgb(0, 165, 181);
      font-weight: bold;
      letter-spacing: 2px;
      background: rgba(255, 255, 255, 0.1);
      padding: 10px 30px;
      border-radius: 8px;
    }
    
    .close-btn {
      position: absolute;
      right: 20px;
      top: 50%;
      transform: translateY(-50%);
      font-size: 24px;
      color: #ff4949;
      cursor: pointer;
      padding: 10px;
      transition: all 0.3s ease;
      
      &:hover {
        color: #ff6d6d;
        transform: translateY(-50%) scale(1.1);
      }
    }
  }
  
  .container {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    padding: 20px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    backdrop-filter: blur(10px);
    max-height: calc(80vh - 100px);
    overflow-y: auto;
    
    &::-webkit-scrollbar {
      width: 8px;
    }
    
    &::-webkit-scrollbar-track {
      background: rgba(255, 255, 255, 0.1);
      border-radius: 4px;
    }
    
    &::-webkit-scrollbar-thumb {
      background: rgba(255, 255, 255, 0.3);
      border-radius: 4px;
      
      &:hover {
        background: rgba(255, 255, 255, 0.5);
      }
    }
  }
  
  .itemres {
    background: #fff;
    min-width: 140px;
    height: 140px;
    border-radius: 4px;
    border: none;
    font-weight: bold;
    margin-right: 20px;
    margin-bottom: 20px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
    
    &:hover {
      transform: translateY(-5px);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
    }
    
    .cont {
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 10px;
      width: 100%;
      
      span {
        font-size: 24px;
        color: rgb(0, 165, 181);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;
        text-align: center;
      }
    }
    
    &.numberOver::before {
      content: attr(data-id);
      width: 30px;
      height: 22px;
      line-height: 22px;
      background-color: #fff;
      position: absolute;
      bottom: 0;
      left: 0;
      font-size: 14px;
      border-radius: 0 0 0 4px;
      color: #666;
      box-shadow: -1px -1px 3px rgba(0, 0, 0, 0.1);
    }
    
    img {
      border-radius: 4px;
      object-fit: cover;
    }
  }
}

@keyframes bounce-in {
  0% {
    transform: scale(0.3);
    opacity: 0;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.8;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

#tags {
  ul {
    li {
      a {
        font-size: 14px;
        white-space: nowrap;
        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        text-align: center;
        display: inline-block;
      }
    }
  }
}
</style>
